#include "h_stm32_hal_uart.h"
#include "h_stm32_hal_defines.h"
#include <stdio.h>
#include <string.h>
/*
    For some reason, f0xx series chip use different register
*/
#define H_STM32_UART_0XX                        1

static UART_HandleTypeDef *print_uart = NULL;
#define UART_PRINT_TIMEOUT                      0xFFFF

#ifdef __GNUC__  
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
#else  
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
#endif /* __GNUC__ */  

PUTCHAR_PROTOTYPE  
{
    if(NULL != print_uart) {
    HAL_UART_Transmit(print_uart , (uint8_t *)&ch, 1, UART_PRINT_TIMEOUT);
    }
    return ch;  
}  

int _write(int file, char *ptr, int len)
{
  int DataIdx;

    for (DataIdx = 0; DataIdx < len; DataIdx++) {
       __io_putchar( *ptr++ );
    }
    return len;
}


void h_stm32_hal_uart_printf_init(UART_HandleTypeDef *handle)
{
    print_uart = handle;
}

h_stm32_hal_uart_t h_stm32_hal_uart_init(UART_HandleTypeDef *handle, \
    h_stm32_hal_uart_state rxEnable, DMA_HandleTypeDef *dma, \
    unsigned short rxlen, void *callback)
{
    h_stm32_hal_uart_t uart_t;
    uart_t.uartHandle = handle;
    if(h_stm32_hal_uart_enable == rxEnable) {
        uart_t.uartRxDMA = dma;
        uart_t.rxDMAEnable = rxEnable;
        uart_t.rxLength = rxlen;
        uart_t.receiveCallback = callback;
    }
    return uart_t;
}

h_stm32_hal_uart_state h_stm32_hal_uart_startReceive(h_stm32_hal_uart_t *uart_t)
{
    if(h_stm32_hal_uart_enable != uart_t->rxDMAEnable) {
        return h_stm32_hal_uart_disable;
    }
    uart_t->rxBuffer = (unsigned char *)H_STM32_MALLOC(sizeof(unsigned char) * uart_t->rxLength);
    if(NULL == uart_t->rxBuffer) {
        return h_stm32_hal_uart_malloc_failed;
    }

    __HAL_UART_ENABLE_IT(uart_t->uartHandle, UART_IT_IDLE);
    HAL_UART_Receive_DMA(uart_t->uartHandle, uart_t->rxBuffer, uart_t->rxLength);

    return h_stm32_hal_uart_ok;
}

h_stm32_hal_uart_state h_stm32_hal_uart_handleReceive(h_stm32_hal_uart_t *uart_t)
{
    unsigned int tmp_flag = 0;
    unsigned int temp;
    unsigned short dataRealLength;

    if(h_stm32_hal_uart_enable != uart_t->rxDMAEnable) {
        return h_stm32_hal_uart_disable;
    }

    tmp_flag =__HAL_UART_GET_FLAG(uart_t->uartHandle, UART_FLAG_IDLE);

    if((tmp_flag != RESET)) {

        __HAL_UART_CLEAR_IDLEFLAG(uart_t->uartHandle);
#if H_STM32_UART_0XX
        temp = uart_t->uartHandle->Instance->ISR;  //CLear ISR register
        temp = uart_t->uartHandle->Instance->RDR;  //Clear RDR register
        HAL_UART_DMAStop(uart_t->uartHandle); //
        temp  = uart_t->uartRxDMA->Instance->CNDTR; // Get the data space left
#else
        temp = uart_t->uartHandle->Instance->SR;  //CLear ISR register
        temp = uart_t->uartHandle->Instance->DR;  //Clear RDR register
        HAL_UART_DMAStop(uart_t->uartHandle); //
        temp  = uart_t->uartRxDMA->Instance->NDTR; // Get the data space left
#endif
        dataRealLength =  uart_t->rxLength - temp;  //Get the real data
        // Callback handle
        if(dataRealLength < uart_t->rxLength && dataRealLength > 0) {
            uart_t->receiveCallback(uart_t->rxBuffer, dataRealLength);
        }
        HAL_UART_Receive_DMA(uart_t->uartHandle, uart_t->rxBuffer, uart_t->rxLength);
    }
    return h_stm32_hal_uart_ok;
}

#define STR2HEX_LEN     128
void str2hex(unsigned char *pAddr, unsigned short len, unsigned char *str2hexdata)
{
    unsigned short charCnt;
    const unsigned char hex[] = "0123456789ABCDEF";
    unsigned char *pStr = str2hexdata;

    for (charCnt = 0; charCnt < len; charCnt++) {
        *pStr++ = hex[*pAddr >> 4];
        *pStr++ = hex[*pAddr++ & 0x0F];
    }

    *pStr = '\0';

    pStr = NULL;
}



void debug_hex(unsigned char *data, unsigned short len)
{
    unsigned short i = 0;
    unsigned short d_len = 0;

    unsigned char *tdata = data;

    unsigned char str2hexdata[STR2HEX_LEN + STR2HEX_LEN + 1];

    for(i = 0; i <= len; i += STR2HEX_LEN) {
        d_len = len < STR2HEX_LEN ? len : STR2HEX_LEN;

        str2hex(tdata, d_len, &str2hexdata[0]);

        printf("%s", &str2hexdata[0]);

        if(len < STR2HEX_LEN) {
            break;
        }

        len -= STR2HEX_LEN;
        tdata += STR2HEX_LEN;
    }


    printf("\r\n");
}

